package processor

import (
	"gitee.com/Luna-CY/hui-hui/internal/logger"
	"gitee.com/Luna-CY/hui-hui/internal/runtime"
	"gitee.com/Luna-CY/hui-hui/internal/toolbox/crontab"
	"github.com/shirou/gopsutil/v3/process"
	"os"
	"os/exec"
	"path/filepath"
	"sync"
)

var logs = filepath.Join(runtime.Data, "logs")

type State int

const (
	StateStarting    = State(iota) + 1 // 启动中
	StateStarted                       // 已启动
	StateStartFailed                   // 启动失败
	StateRunError                      // 运行异常
	StateRestarting                    // 重启中
	StateReloading                     // 重载配置中
	StateStopping                      // 退出中
	StateStopped                       // 已退出
)

// Process 进程模型
type Process struct {
	Username string // 用户
	Pid      int32  // 进程ID
	PPid     int32  // 父进程ID
	Command  string // 进程命令
}

// Application 应用模型
type Application struct {
	c *exec.Cmd // 进程对象

	name         string             // 应用名称，必须唯一，用于创建日志文件等
	pid          int32              // 进程ID，对应的系统进程ID，状态为Started时有效
	command      string             // 进程命令
	args         []string           // 启动参数
	environments []string           // 环境变量
	working      string             // 运行目录
	state        State              // 运行状态
	output       *os.File           // 进程的输出日志
	restart      bool               // 运行异常时是否重启
	quiting      bool               // 是否正在退出，此标志位true时不能重启
	callback     func(State, error) // 状态通知函数
}

var once sync.Once
var instance *Processor

func Single(crontab *crontab.Crontab) *Processor {
	once.Do(func() {
		instance = &Processor{crontab: crontab, system: make(map[int32]*process.Process), application: make(map[string]*Application)}
		if err := instance.crontab.AddSystem("* * * * * *", instance.counter); nil != err {
			logger.GetLogger().Sugar().Errorf("进程管理器: 注册系统任务失败: %s", err)

			os.Exit(1)
		}

		if err := instance.crontab.AddSystem("* * * * * *", instance.keepalive); nil != err {
			logger.GetLogger().Sugar().Errorf("进程管理器: 注册系统任务失败: %s", err)

			os.Exit(1)
		}

		logger.GetLogger().Sugar().Info("进程管理器已启动")
	})

	return instance
}

// Processor 进程管理器
type Processor struct {
	crontab *crontab.Crontab

	mutex       sync.RWMutex               // 资源锁
	quiting     bool                       // 进程管理器正在退出
	system      map[int32]*process.Process // 系统进程
	application map[string]*Application    // 应用进程
}
